/***** JFlex specification for Scheme *****/

package com.bitbakery.plugin.scheme.lang.lexer;

import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import com.bitbakery.plugin.scheme.lang.lexer.SchemeTokenTypes;
import java.util.*;
import java.lang.reflect.Field;
import org.jetbrains.annotations.NotNull;

%%

%class _SchemeLexer
%implements FlexLexer, SchemeTokenTypes
%unicode
%public

%function advance
%type IElementType



/***** Custom user code *****/

%{
    StringBuffer string = new StringBuffer();
%}




/***** Macros - Regular expressions *****/

LineTerminator=\r|\n|\r\n
InputCharacter=[^\r\n]
WhiteSpace={LineTerminator}|[ \t\f]

LineComment=([ \t\f]*";"{InputCharacter}*{LineTerminator})
MultiLineComment=(({LineComment})+[ \t\f]*";"{InputCharacter}*)

/** TODO - This doesn't work around (define ...) statements! *******************/
BlockComment={MultiLineComment}|("#!".*"!#")

Digit=[0-9]
IntegerLiteral=(0|([1-9]({Digit})*))

ExponentPart=[Ee]["+""-"]?({Digit})*
FloatingPointLiteral1=({Digit})+"."({Digit})*({ExponentPart})?
FloatingPointLiteral2="."({Digit})+({ExponentPart})?
FloatingPointLiteral3=({Digit})+({ExponentPart})
FloatingPointLiteral4=({Digit})+
FloatLiteral=({FloatingPointLiteral1})|({FloatingPointLiteral2})|({FloatingPointLiteral3})|({FloatingPointLiteral4})

CharacterLiteral="#\\".

NumericLiteral=["+""-"]?({IntegerLiteral})|({FloatLiteral})

/**** TODO - Include support for pipe-delimited symbols **************/
Symbol=[A-Za-z0-9!@#$%<>_~/?&\^\+\*\-=\.\?:]*

EscapeSequence=\\[^\r\n]
StringLiteral=\"([^\\\"]|{EscapeSequence})*(\"|\\)?


%%

{WhiteSpace}    { return WHITESPACE; }
{LineComment}   { return LINE_COMMENT; }
{BlockComment}  { return BLOCK_COMMENT; }
{NumericLiteral} { return NUMERIC_LITERAL; }
{StringLiteral} { return STRING_LITERAL; }


/** TODO - Any other tokens? Exception stuff? Other keyword-style, commonly used macros? *******************/

"("             { return LEFT_PAREN; }
")"             { return RIGHT_PAREN; }

"#"[Tt]            { return TRUE; }
"#"[Ff]            { return FALSE; }
[Nn][Ii][Ll]    { return NIL; }

[Qq][Uu][Oo][Tt][Ee]        { return QUOTE_KEYWORD; }
[Ll][Aa][Mm][Bb][Dd][Aa]    { return LAMBDA; }
[Cc][Oo][Nn][Dd]            { return COND; }
[Ii][Ff]                    { return IF; }
[Ll][Ee][Tt]                { return LET; }
[Ll][Ee][Tt]"*"             { return LET_STAR; }
[Ll][Ee][Tt][Rr][Ee][Cc]    { return LETREC; }
[Ss][Ee][Tt]"!"             { return SET; }
[Cc][Oo][Nn][Ss]            { return CONS; }
[Cc][Aa][Rr]                { return CAR; }
[Cc][Dd][Rr]                { return CDR; }

"`"             { return BACKQUOTE; }
"'"             { return QUOTE; }
","             { return COMMA; }
",@"            { return COMMA_AT; }
"#'"            { return SHARP_QUOTE; }

[Dd][Ee][Ff][Ii][Nn][Ee]                             { return DEFINE; }
[Dd][Ee][Ff][Ii][Nn][Ee]"-"[Ss][Yy][Nn][Tt][Aa][xx]  { return DEFINE_SYNTAX; }
[Ss][Yy][Nn][Tt][Aa][xx]"-"[Rr][Uu][Ll][Ee][Ss]      { return SYNTAX_RULES; }

{Symbol}        { return SYMBOL; }

.               { return BAD_CHARACTER; }